package com.xiaoze.springcloud.config;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.*;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;

@Slf4j
@EnableWebSecurity
@Configuration
class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private MyPasswordEncoder myPasswordEncoder;

    @Bean
    LoginAuthenticationFilter loginAuthenticationFilter() throws Exception {
        LoginAuthenticationFilter filter = new LoginAuthenticationFilter();
        filter.setFilterProcessesUrl("/doLogin");
        filter.setAuthenticationSuccessHandler((req, resp, authentication) -> {
            resp.setContentType(MediaType.APPLICATION_JSON_VALUE);
            PrintWriter writer = resp.getWriter();
//                // 下面处理所有用户信息，保存用户信息
//                Hr hr = (Hr) authentication.getPrincipal();
            String msg = JSON.toJSONString(authentication);
            writer.write(msg);
            writer.flush();
            writer.close();
        });

        filter.setAuthenticationFailureHandler((req, resp, e) -> {

            resp.setContentType(MediaType.APPLICATION_JSON_VALUE);
            PrintWriter writer = resp.getWriter();
            if (e instanceof BadCredentialsException) {
                log.error("用户名或密码错误，请检查");
            } else if(e instanceof LockedException){
                log.error("账户被锁定，请联系管理员");
            } else if(e instanceof CredentialsExpiredException){
                log.error("密码已过期，请联系管理员");
            } else if(e instanceof DisabledException){
                log.error("账户被禁用，请联系管理员");
            } else {
                log.error("登录失败!");
            }

            String msg = "登录失败" + "所有信息";
            writer.write(msg);
            writer.flush();
            writer.close();
        });

        filter.setAuthenticationManager(authenticationManagerBean());
        return filter;
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.csrf().disable()
            .exceptionHandling()
            .authenticationEntryPoint((request, response, authException) -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED))
            .and()
            .authorizeRequests()
            .antMatchers("/oauth/**")
            .permitAll()//不需要登录即可通过的URL
            .and()
            .authorizeRequests()
            .anyRequest().authenticated()
            .and()
            .logout()
            //自定义退出url
            .logoutUrl("/logoutAuth")
            .logoutSuccessHandler((req, resp, authentication) -> {
                resp.setContentType(MediaType.APPLICATION_JSON_VALUE);
                PrintWriter writer = resp.getWriter();
                writer.write("注销退出成功");
                writer.flush();
                writer.close();
            })
            .clearAuthentication(true)
            .invalidateHttpSession(true);

        http.addFilterAt(loginAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService)
            .passwordEncoder(myPasswordEncoder);
    }

}
